package com.minio.learning.example;

import com.minio.learning.client.MinioClientWrapper;
import com.minio.learning.config.MinioConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.charset.StandardCharsets;

/**
 * MinIO 进阶示例
 * 
 * 学习目标：
 * 1. 生成预签名 URL - 文件分享
 * 2. 获取对象元数据
 * 3. 复制对象
 * 4. 上传和下载字节数据
 * 5. 实际应用场景
 */
public class AdvancedExample {
    
    private static final Logger logger = LoggerFactory.getLogger(AdvancedExample.class);
    
    public static void main(String[] args) {
        logger.info("========== MinIO 进阶示例 ==========\n");
        
        // 初始化客户端
        MinioClientWrapper client = new MinioClientWrapper();
        String bucketName = "advanced-bucket";
        
        try {
            // 1. 创建测试桶
            demonstrateBucketSetup(client, bucketName);
            
            // 2. 演示预签名 URL（文件分享）
            demonstratePresignedUrl(client, bucketName);
            
            // 3. 演示字节数据上传下载
            demonstrateByteOperations(client, bucketName);
            
            // 4. 演示对象复制
            demonstrateCopyObject(client, bucketName);
            
            // 5. 演示对象元数据
            demonstrateObjectMetadata(client, bucketName);
            
            // 6. 实际应用场景示例
            demonstrateRealWorldScenarios(client, bucketName);
            
            logger.info("\n✅ 所有进阶示例执行完成！");
            
        } catch (Exception e) {
            logger.error("❌ 执行示例时出错: {}", e.getMessage(), e);
        }
    }
    
    /**
     * 示例 1：设置测试桶
     */
    private static void demonstrateBucketSetup(MinioClientWrapper client, String bucketName) {
        logger.info("\n========== 示例 1：创建测试桶 ==========");
        client.createBucket(bucketName);
    }
    
    /**
     * 示例 2：预签名 URL（最重要的高级功能）
     * 
     * 使用场景：
     * 1. 生成下载链接分享给他人
     * 2. 前端直接上传文件
     * 3. 临时公开私有文件
     */
    private static void demonstratePresignedUrl(MinioClientWrapper client, String bucketName) {
        logger.info("\n========== 示例 2：预签名 URL ==========");
        
        // 先上传一个文件
        String objectName = "shared-file.txt";
        String content = "这是一个可以通过临时链接访问的文件！";
        byte[] data = content.getBytes(StandardCharsets.UTF_8);
        
        client.uploadBytes(bucketName, objectName, data, "text/plain");
        
        // 生成 1 小时有效的下载链接
        logger.info("\n生成下载链接（1 小时有效）：");
        String url1Hour = client.generatePresignedUrl(bucketName, objectName, 3600);
        
        // 生成 7 天有效的下载链接
        logger.info("\n生成下载链接（7 天有效）：");
        String url7Days = client.generatePresignedUrl(bucketName, objectName, 7 * 24 * 3600);
        
        logger.info("\n💡 使用提示：");
        logger.info("   - 复制上面的 URL 在浏览器中打开，可以直接下载文件");
        logger.info("   - 不需要登录或认证");
        logger.info("   - URL 过期后自动失效");
        logger.info("   - 适合分享文件给他人");
    }
    
    /**
     * 示例 3：字节数据操作
     * 
     * 使用场景：
     * - 上传动态生成的内容
     * - 直接处理内存中的数据
     * - 不需要保存到本地文件
     */
    private static void demonstrateByteOperations(MinioClientWrapper client, String bucketName) {
        logger.info("\n========== 示例 3：字节数据操作 ==========");
        
        // 场景 1：上传 JSON 配置
        logger.info("\n场景 1：上传 JSON 配置文件");
        String jsonConfig = """
                {
                    "appName": "MinIO 学习项目",
                    "version": "1.0.0",
                    "environment": "development"
                }
                """;
        
        client.uploadBytes(
                bucketName,
                "config/app-config.json",
                jsonConfig.getBytes(StandardCharsets.UTF_8),
                "application/json"
        );
        
        // 场景 2：下载并直接使用数据
        logger.info("\n场景 2：下载数据到内存");
        byte[] downloadedData = client.downloadBytes(bucketName, "config/app-config.json");
        
        if (downloadedData != null) {
            String content = new String(downloadedData, StandardCharsets.UTF_8);
            logger.info("下载的配置内容：\n{}", content);
        }
        
        // 场景 3：生成报表并上传
        logger.info("\n场景 3：生成报表并上传");
        String report = generateReport();
        client.uploadBytes(
                bucketName,
                "reports/2024-report.txt",
                report.getBytes(StandardCharsets.UTF_8),
                "text/plain"
        );
    }
    
    /**
     * 示例 4：对象复制
     * 
     * 使用场景：
     * - 文件备份
     * - 重命名文件
     * - 跨桶移动
     */
    private static void demonstrateCopyObject(MinioClientWrapper client, String bucketName) {
        logger.info("\n========== 示例 4：对象复制 ==========");
        
        // 场景 1：文件备份
        logger.info("\n场景 1：创建备份");
        client.copyObject(
                bucketName, "config/app-config.json",
                bucketName, "backup/app-config-backup.json"
        );
        
        // 场景 2：重命名文件（复制 + 删除）
        logger.info("\n场景 2：重命名文件");
        String oldName = "reports/2024-report.txt";
        String newName = "reports/annual-report-2024.txt";
        
        // 先复制
        boolean copied = client.copyObject(bucketName, oldName, bucketName, newName);
        
        // 再删除原文件
        if (copied) {
            client.deleteObject(bucketName, oldName);
            logger.info("✅ 文件重命名成功：{} -> {}", oldName, newName);
        }
    }
    
    /**
     * 示例 5：对象元数据
     * 
     * 可以获取：
     * - 文件大小
     * - 上传时间
     * - 内容类型
     * - ETag（唯一标识）
     */
    private static void demonstrateObjectMetadata(MinioClientWrapper client, String bucketName) {
        logger.info("\n========== 示例 5：对象元数据 ==========");
        
        // 获取并显示对象信息
        client.getObjectInfo(bucketName, "config/app-config.json");
        client.getObjectInfo(bucketName, "reports/annual-report-2024.txt");
        
        // 检查对象是否存在
        logger.info("\n检查对象是否存在：");
        logger.info("  - config/app-config.json 存在？{}", 
                client.objectExists(bucketName, "config/app-config.json"));
        logger.info("  - not-exist.txt 存在？{}", 
                client.objectExists(bucketName, "not-exist.txt"));
    }
    
    /**
     * 示例 6：实际应用场景
     */
    private static void demonstrateRealWorldScenarios(MinioClientWrapper client, String bucketName) {
        logger.info("\n========== 示例 6：实际应用场景 ==========");
        
        // 场景 1：用户头像上传
        logger.info("\n场景 1：用户头像管理");
        simulateUserAvatarUpload(client, bucketName, "user123");
        
        // 场景 2：日志文件归档
        logger.info("\n场景 2：日志文件归档");
        simulateLogArchive(client, bucketName);
        
        // 场景 3：文件分类存储
        logger.info("\n场景 3：文件分类存储");
        simulateFileOrganization(client, bucketName);
    }
    
    // ==================== 辅助方法 ====================
    
    /**
     * 模拟生成报表
     */
    private static String generateReport() {
        return """
                ====== 年度报告 2024 ======
                
                总用户数：10,000
                活跃用户：8,500
                新增用户：2,500
                
                存储使用：500 GB
                上传文件：15,000
                下载次数：50,000
                
                生成时间：2024-10-23
                ===========================
                """;
    }
    
    /**
     * 模拟用户头像上传
     */
    private static void simulateUserAvatarUpload(MinioClientWrapper client, 
                                                String bucketName, String userId) {
        String avatarContent = "这是用户 " + userId + " 的头像图片数据";
        String objectName = "avatars/" + userId + "/avatar.jpg";
        
        client.uploadBytes(
                bucketName,
                objectName,
                avatarContent.getBytes(),
                "image/jpeg"
        );
        
        // 生成头像访问链接（30 天有效）
        String avatarUrl = client.generatePresignedUrl(bucketName, objectName, 30 * 24 * 3600);
        logger.info("头像访问链接已生成（30 天有效）");
    }
    
    /**
     * 模拟日志归档
     */
    private static void simulateLogArchive(MinioClientWrapper client, String bucketName) {
        String logContent = """
                [2024-10-23 10:00:00] INFO - 应用启动
                [2024-10-23 10:01:23] INFO - 用户登录: user123
                [2024-10-23 10:05:45] WARN - 内存使用率: 85%
                [2024-10-23 10:10:00] INFO - 文件上传成功
                """;
        
        // 按日期归档日志
        String logPath = "logs/2024/10/23/app.log";
        client.uploadBytes(
                bucketName,
                logPath,
                logContent.getBytes(),
                "text/plain"
        );
        
        logger.info("日志已归档到：{}", logPath);
    }
    
    /**
     * 模拟文件分类存储
     */
    private static void simulateFileOrganization(MinioClientWrapper client, String bucketName) {
        // 图片
        client.uploadBytes(bucketName, "images/photo1.jpg", "图片数据".getBytes(), "image/jpeg");
        
        // 文档
        client.uploadBytes(bucketName, "documents/report.pdf", "PDF数据".getBytes(), "application/pdf");
        
        // 视频
        client.uploadBytes(bucketName, "videos/tutorial.mp4", "视频数据".getBytes(), "video/mp4");
        
        logger.info("✅ 文件已按类型分类存储");
        
        // 列出各分类的文件
        logger.info("\n图片文件：");
        client.listObjects(bucketName, "images/");
        
        logger.info("\n文档文件：");
        client.listObjects(bucketName, "documents/");
        
        logger.info("\n视频文件：");
        client.listObjects(bucketName, "videos/");
    }
}

